# Copyright 2010-2015 Free Software Foundation, Inc.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
#
# Contributed by Ken Werner <ken.werner@de.ibm.com>.
#
# Tests OpenCL data types.

load_lib opencl.exp

if { [skip_opencl_tests] } {
    return 0
}

set testfile "datatypes"
set clprogram [remote_download target ${srcdir}/${subdir}/${testfile}.cl]

# Compile the generic OpenCL host app
if { [gdb_compile_opencl_hostapp "${clprogram}" "${testfile}" "" ] != "" } {
    untested ${testfile}.exp
    return -1
}

gdb_exit
gdb_start

# Manually switch the language to opencl
gdb_test_no_output "set language opencl" "No prompt when setting the language to opencl"

# Check OpenCL data types (GDB)
gdb_test "whatis bool" "type = bool"
gdb_test "p sizeof(bool)" " = 1"

gdb_test "whatis char" "type = char"
gdb_test "p sizeof(char)" " = 1"
gdb_test "whatis char2" "type = char2"
gdb_test "p sizeof(char2)" " = 2"
gdb_test "whatis char3" "type = char3"
gdb_test "p sizeof(char3)" " = 4"
gdb_test "whatis char4" "type = char4"
gdb_test "p sizeof(char4)" " = 4"
gdb_test "whatis char8" "type = char8"
gdb_test "p sizeof(char8)" " = 8"
gdb_test "whatis char16" "type = char16"
gdb_test "p sizeof(char16)" " = 16"

gdb_test "whatis unsigned char" "type = unsigned char"
gdb_test "p sizeof(unsigned char)" " = 1"
gdb_test "whatis uchar" "type = uchar"
gdb_test "p sizeof(uchar)" " = 1"
gdb_test "whatis uchar2" "type = uchar2"
gdb_test "p sizeof(uchar2)" " = 2"
gdb_test "whatis uchar3" "type = uchar3"
gdb_test "p sizeof(uchar3)" " = 4"
gdb_test "whatis uchar4" "type = uchar4"
gdb_test "p sizeof(uchar4)" " = 4"
gdb_test "whatis uchar8" "type = uchar8"
gdb_test "p sizeof(uchar8)" " = 8"
gdb_test "whatis uchar16" "type = uchar16"
gdb_test "p sizeof(uchar16)" " = 16"

gdb_test "whatis short" "type = short"
gdb_test "p sizeof(short)" " = 2"
gdb_test "whatis short2" "type = short2"
gdb_test "p sizeof(short2)" " = 4"
gdb_test "whatis short3" "type = short3"
gdb_test "p sizeof(short3)" " = 8"
gdb_test "whatis short4" "type = short4"
gdb_test "p sizeof(short4)" " = 8"
gdb_test "whatis short8" "type = short8"
gdb_test "p sizeof(short8)" " = 16"
gdb_test "whatis short16" "type = short16"
gdb_test "p sizeof(short16)" " = 32"

gdb_test "whatis unsigned short" "type = unsigned short"
gdb_test "p sizeof(unsigned short)" " = 2"
gdb_test "whatis ushort" "type = ushort"
gdb_test "p sizeof(ushort)" " = 2"
gdb_test "whatis ushort2" "type = ushort2"
gdb_test "p sizeof(ushort2)" " = 4"
gdb_test "whatis ushort3" "type = ushort3"
gdb_test "p sizeof(ushort3)" " = 8"
gdb_test "whatis ushort4" "type = ushort4"
gdb_test "p sizeof(ushort4)" " = 8"
gdb_test "whatis ushort8" "type = ushort8"
gdb_test "p sizeof(ushort8)" " = 16"
gdb_test "whatis ushort16" "type = ushort16"
gdb_test "p sizeof(ushort16)" " = 32"

gdb_test "whatis int" "type = int"
gdb_test "p sizeof(int)" " = 4"
gdb_test "whatis int2" "type = int2"
gdb_test "p sizeof(int2)" " = 8"
gdb_test "whatis int3" "type = int3"
gdb_test "p sizeof(int3)" " = 16"
gdb_test "whatis int4" "type = int4"
gdb_test "p sizeof(int4)" " = 16"
gdb_test "whatis int8" "type = int8"
gdb_test "p sizeof(int8)" " = 32"
gdb_test "whatis int16" "type = int16"
gdb_test "p sizeof(int16)" " = 64"

gdb_test "whatis unsigned int" "type = unsigned int"
gdb_test "p sizeof(unsigned int)" " = 4"
gdb_test "whatis uint" "type = uint"
gdb_test "p sizeof(uint)" " = 4"
gdb_test "whatis uint2" "type = uint2"
gdb_test "p sizeof(uint2)" " = 8"
gdb_test "whatis uint3" "type = uint3"
gdb_test "p sizeof(uint3)" " = 16"
gdb_test "whatis uint4" "type = uint4"
gdb_test "p sizeof(uint4)" " = 16"
gdb_test "whatis uint8" "type = uint8"
gdb_test "p sizeof(uint8)" " = 32"
gdb_test "whatis uint16" "type = uint16"
gdb_test "p sizeof(uint16)" " = 64"

gdb_test "whatis long" "type = long"
gdb_test "p sizeof(long)" " = 8"
gdb_test "whatis long2" "type = long2"
gdb_test "p sizeof(long2)" " = 16"
gdb_test "whatis long3" "type = long3"
gdb_test "p sizeof(long3)" " = 32"
gdb_test "whatis long4" "type = long4"
gdb_test "p sizeof(long4)" " = 32"
gdb_test "whatis long8" "type = long8"
gdb_test "p sizeof(long8)" " = 64"
gdb_test "whatis long16" "type = long16"
gdb_test "p sizeof(long16)" " = 128"

gdb_test "whatis unsigned long" "type = unsigned long"
gdb_test "p sizeof(unsigned long)" " = 8"
gdb_test "whatis ulong" "type = ulong"
gdb_test "p sizeof(ulong)" " = 8"
gdb_test "whatis ulong2" "type = ulong2"
gdb_test "p sizeof(ulong2)" " = 16"
gdb_test "whatis ulong3" "type = ulong3"
gdb_test "p sizeof(ulong3)" " = 32"
gdb_test "whatis ulong4" "type = ulong4"
gdb_test "p sizeof(ulong4)" " = 32"
gdb_test "whatis ulong8" "type = ulong8"
gdb_test "p sizeof(ulong8)" " = 64"
gdb_test "whatis ulong16" "type = ulong16"
gdb_test "p sizeof(ulong16)" " = 128"

gdb_test "whatis half" "type = half"
gdb_test "p sizeof(half)" " = 2"
gdb_test "whatis half2" "type = half2"
gdb_test "p sizeof(half2)" " = 4"
gdb_test "whatis half3" "type = half3"
gdb_test "p sizeof(half3)" " = 8"
gdb_test "whatis half4" "type = half4"
gdb_test "p sizeof(half4)" " = 8"
gdb_test "whatis half8" "type = half8"
gdb_test "p sizeof(half8)" " = 16"
gdb_test "whatis half16" "type = half16"
gdb_test "p sizeof(half16)" " = 32"

gdb_test "whatis float" "type = float"
gdb_test "p sizeof(float)" " = 4"
gdb_test "whatis float2" "type = float2"
gdb_test "p sizeof(float2)" " = 8"
gdb_test "whatis float3" "type = float3"
gdb_test "p sizeof(float3)" " = 16"
gdb_test "whatis float4" "type = float4"
gdb_test "p sizeof(float4)" " = 16"
gdb_test "whatis float8" "type = float8"
gdb_test "p sizeof(float8)" " = 32"
gdb_test "whatis float16" "type = float16"
gdb_test "p sizeof(float16)" " = 64"

gdb_test "whatis double" "type = double"
gdb_test "p sizeof(double)" " = 8"
gdb_test "whatis double2" "type = double2"
gdb_test "p sizeof(double2)" " = 16"
gdb_test "whatis double3" "type = double3"
gdb_test "p sizeof(double3)" " = 32"
gdb_test "whatis double4" "type = double4"
gdb_test "p sizeof(double4)" " = 32"
gdb_test "whatis double8" "type = double8"
gdb_test "p sizeof(double8)" " = 64"
gdb_test "whatis double16" "type = double16"
gdb_test "p sizeof(double16)" " = 128"

# Set the language back to the default: "auto; currently c"
gdb_test_no_output "set language c" "No prompt when setting the language to c"
gdb_test_no_output "set language auto" "No prompt when setting the language to auto"

# Load the OpenCL app
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${objdir}/${subdir}/${testfile}

# Set breakpoint at the OpenCL kernel
gdb_test "tbreak testkernel" \
    "" \
    "Set pending breakpoint" \
    ".*Function \"testkernel\" not defined.*Make breakpoint pending.*y or \\\[n\\\]. $" \
    "y"

gdb_run_cmd
gdb_test "" ".*reakpoint.*1.*testkernel.*" "run"

# Continue to the marker
gdb_breakpoint [gdb_get_line_number "marker" "${clprogram}"]
gdb_continue_to_breakpoint "marker"

# Check if the language was switched to opencl
gdb_test "show language" "The current source language is \"auto; currently opencl\"\."

# Retrieve some information about the OpenCL version and the availability of extensions
set opencl_version [get_integer_valueof "opencl_version" 0]
set have_cl_khr_fp64 [get_integer_valueof "have_cl_khr_fp64" 0]
set have_cl_khr_fp16 [get_integer_valueof "have_cl_khr_fp16" 0]

# Check OpenCL data types (DWARF)
gdb_test "whatis b" "type = bool"
gdb_test "p sizeof(b)" " = 1"
gdb_test "print b" " = (false|0)"

gdb_test "whatis c" "type = char"
gdb_test "p sizeof(c)" " = 1"
gdb_test "print/d c" " = 1"
gdb_test "whatis c2" "type = char2"
gdb_test "p sizeof(c2)" " = 2"
gdb_test "print c2" " = \\{1, 2\\}"
if { ${opencl_version} >= 110 } {
  gdb_test "whatis c3" "type = char3"
  gdb_test "p sizeof(c3)" " = 4"
  gdb_test "print c3" " = \\{1, 2, 3\\}"
}
gdb_test "whatis c4" "type = char4"
gdb_test "p sizeof(c4)" " = 4"
gdb_test "print c4" " = \\{1, 2, 3, 4\\}"
gdb_test "whatis c8" "type = char8"
gdb_test "p sizeof(c8)" " = 8"
gdb_test "print c8" " = \\{1, 2, 3, 4, 5, 6, 7, 8\\}"
gdb_test "whatis c16" "type = char16"
gdb_test "p sizeof(c16)" " = 16"
gdb_test "print c16" " = \\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16\\}"

gdb_test "whatis uc" "type = uchar"
gdb_test "p sizeof(uc)" " = 1"
gdb_test "print/d uc" " = 1"
gdb_test "whatis uc2" "type = uchar2"
gdb_test "p sizeof(uc2)" " = 2"
gdb_test "print uc2" " = \\{1, 2\\}"
if { ${opencl_version} >= 110 } {
  gdb_test "whatis uc3" "type = uchar3"
  gdb_test "p sizeof(uc3)" " = 4"
  gdb_test "print uc3" " = \\{1, 2, 3\\}"
}
gdb_test "whatis uc4" "type = uchar4"
gdb_test "p sizeof(uc4)" " = 4"
gdb_test "print uc4" " = \\{1, 2, 3, 4\\}"
gdb_test "whatis uc8" "type = uchar8"
gdb_test "p sizeof(uc8)" " = 8"
gdb_test "print uc8" " = \\{1, 2, 3, 4, 5, 6, 7, 8\\}"
gdb_test "whatis uc16" "type = uchar16"
gdb_test "p sizeof(uc16)" " = 16"
gdb_test "print uc16" " = \\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16\\}"

gdb_test "whatis s" "type = short"
gdb_test "p sizeof(s)" " = 2"
gdb_test "print s" " = -1"
gdb_test "whatis s2" "type = short2"
gdb_test "p sizeof(s2)" " = 4"
gdb_test "print s2" " = \\{-1, -2\\}"
if { ${opencl_version} >= 110 } {
  gdb_test "whatis s3" "type = short3"
  gdb_test "p sizeof(s3)" " = 8"
  gdb_test "print s3" " = \\{-1, -2, -3\\}"
}
gdb_test "whatis s4" "type = short4"
gdb_test "p sizeof(s4)" " = 8"
gdb_test "print s4" " = \\{-1, -2, -3, -4\\}"
gdb_test "whatis s8" "type = short8"
gdb_test "p sizeof(s8)" " = 16"
gdb_test "print s8" " = \\{-1, -2, -3, -4, -5, -6, -7, -8\\}"
gdb_test "whatis s16" "type = short16"
gdb_test "p sizeof(s16)" " = 32"
gdb_test "print s16" " = \\{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16\\}"

gdb_test "whatis us" "type = ushort"
gdb_test "p sizeof(us)" " = 2"
gdb_test "print us" " = 1"
gdb_test "whatis us2" "type = ushort2"
gdb_test "p sizeof(us2)" " = 4"
gdb_test "print us2" " = \\{1, 2\\}"
if { ${opencl_version} >= 110 } {
  gdb_test "whatis us3" "type = ushort3"
  gdb_test "p sizeof(us3)" " = 8"
  gdb_test "print us3" " = \\{1, 2, 3\\}"
}
gdb_test "whatis us4" "type = ushort4"
gdb_test "p sizeof(us4)" " = 8"
gdb_test "print us4" " = \\{1, 2, 3, 4\\}"
gdb_test "whatis us8" "type = ushort8"
gdb_test "p sizeof(us8)" " = 16"
gdb_test "print us8" " = \\{1, 2, 3, 4, 5, 6, 7, 8\\}"
gdb_test "whatis us16" "type = ushort16"
gdb_test "p sizeof(us16)" " = 32"
gdb_test "print us16" " = \\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16\\}"

gdb_test "whatis i" "type = int"
gdb_test "p sizeof(i)" " = 4"
gdb_test "print i" " = -1"
gdb_test "whatis i2" "type = int2"
gdb_test "p sizeof(i2)" " = 8"
gdb_test "print i2" " = \\{-1, -2\\}"
if { ${opencl_version} >= 110 } {
  gdb_test "whatis i3" "type = int3"
  gdb_test "p sizeof(i3)" " = 16"
  gdb_test "print i3" " = \\{-1, -2, -3\\}"
}
gdb_test "whatis i4" "type = int4"
gdb_test "p sizeof(i4)" " = 16"
gdb_test "print i4" " = \\{-1, -2, -3, -4\\}"
gdb_test "whatis i8" "type = int8"
gdb_test "p sizeof(i8)" " = 32"
gdb_test "print i8" " = \\{-1, -2, -3, -4, -5, -6, -7, -8\\}"
gdb_test "whatis i16" "type = int16"
gdb_test "p sizeof(i16)" " = 64"
gdb_test "print i16" " = \\{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16\\}"

gdb_test "whatis ui" "type = uint"
gdb_test "p sizeof(ui)" " = 4"
gdb_test "print ui" " = 1"
gdb_test "whatis ui2" "type = uint2"
gdb_test "p sizeof(ui2)" " = 8"
gdb_test "print ui2" " = \\{1, 2\\}"
if { ${opencl_version} >= 110 } {
  gdb_test "whatis ui3" "type = uint3"
  gdb_test "p sizeof(ui3)" " = 16"
  gdb_test "print ui3" " = \\{1, 2, 3\\}"
}
gdb_test "whatis ui4" "type = uint4"
gdb_test "p sizeof(ui4)" " = 16"
gdb_test "print ui4" " = \\{1, 2, 3, 4\\}"
gdb_test "whatis ui8" "type = uint8"
gdb_test "p sizeof(ui8)" " = 32"
gdb_test "print ui8" " = \\{1, 2, 3, 4, 5, 6, 7, 8\\}"
gdb_test "whatis ui16" "type = uint16"
gdb_test "p sizeof(ui16)" " = 64"
gdb_test "print ui16" " = \\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16\\}"

gdb_test "whatis l" "type = long"
gdb_test "p sizeof(l)" " = 8"
gdb_test "print l" " = -1"
gdb_test "whatis l2" "type = long2"
gdb_test "p sizeof(l2)" " = 16"
gdb_test "print l2" " = \\{-1, -2\\}"
if { ${opencl_version} >= 110 } {
  gdb_test "whatis l3" "type = long3"
  gdb_test "p sizeof(l3)" " = 32"
  gdb_test "print l3" " = \\{-1, -2, -3\\}"
}
gdb_test "whatis l4" "type = long4"
gdb_test "p sizeof(l4)" " = 32"
gdb_test "print l4" " = \\{-1, -2, -3, -4\\}"
gdb_test "whatis l8" "type = long8"
gdb_test "p sizeof(l8)" " = 64"
gdb_test "print l8" " = \\{-1, -2, -3, -4, -5, -6, -7, -8\\}"
gdb_test "whatis l16" "type = long16"
gdb_test "p sizeof(l16)" " = 128"
gdb_test "print l16" " = \\{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16\\}"

gdb_test "whatis ul" "type = ulong"
gdb_test "p sizeof(ul)" " = 8"
gdb_test "print ul" " = 1"
gdb_test "whatis ul2" "type = ulong2"
gdb_test "p sizeof(ul2)" " = 16"
gdb_test "print ul2" " = \\{1, 2\\}"
if { ${opencl_version} >= 110 } {
  gdb_test "whatis ul3" "type = ulong3"
  gdb_test "p sizeof(ul3)" " = 32"
  gdb_test "print ul3" " = \\{1, 2, 3\\}"
}
gdb_test "whatis ul4" "type = ulong4"
gdb_test "p sizeof(ul4)" " = 32"
gdb_test "print ul4" " = \\{1, 2, 3, 4\\}"
gdb_test "whatis ul8" "type = ulong8"
gdb_test "p sizeof(ul8)" " = 64"
gdb_test "print ul8" " = \\{1, 2, 3, 4, 5, 6, 7, 8\\}"
gdb_test "whatis ul16" "type = ulong16"
gdb_test "p sizeof(ul16)" " = 128"
gdb_test "print ul16" " = \\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16\\}"

gdb_test "whatis ph" "type = half \\*"
gdb_test "whatis *ph" "type = half"
gdb_test "p sizeof(*ph)" " = 2"

if { ${have_cl_khr_fp16} } {
  gdb_test "whatis h" "type = half"
  gdb_test "p sizeof(h)" " = 2"
  gdb_test "print h" " = 1"
  gdb_test "whatis h2" "type = half2"
  gdb_test "p sizeof(h2)" " = 4"
  gdb_test "print h2" " = \\{1, 2\\}"
  if { ${opencl_version} >= 110 } {
    gdb_test "whatis h3" "type = half3"
    gdb_test "p sizeof(h3)" " = 8"
    gdb_test "print h3" " = \\{1, 2, 3\\}"
  }
  gdb_test "whatis h4" "type = half4"
  gdb_test "p sizeof(h4)" " = 8"
  gdb_test "print h4" " = \\{1, 2, 3, 4\\}"
  gdb_test "whatis h8" "type = half8"
  gdb_test "p sizeof(h8)" " = 16"
  gdb_test "print h8" " = \\{1, 2, 3, 4, 5, 6, 7, 8\\}"
  gdb_test "whatis h16" "type = half16"
  gdb_test "p sizeof(h16)" " = 16"
  gdb_test "print h16" " = \\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16\\}"
}

gdb_test "whatis f" "type = float"
gdb_test "p sizeof(f)" " = 4"
gdb_test "print f" " = 1"
gdb_test "whatis f2" "type = float2"
gdb_test "p sizeof(f2)" " = 8"
gdb_test "print f2" " = \\{1, 2\\}"
if { ${opencl_version} >= 110 } {
  gdb_test "whatis f3" "type = float3"
  gdb_test "p sizeof(f3)" " = 16"
  gdb_test "print f3" " = \\{1, 2, 3\\}"
}
gdb_test "whatis f4" "type = float4"
gdb_test "p sizeof(f4)" " = 16"
gdb_test "print f4" " = \\{1, 2, 3, 4\\}"
gdb_test "whatis f8" "type = float8"
gdb_test "p sizeof(f8)" " = 32"
gdb_test "print f8" " = \\{1, 2, 3, 4, 5, 6, 7, 8\\}"
gdb_test "whatis f16" "type = float16"
gdb_test "p sizeof(f16)" " = 64"
gdb_test "print f16" " = \\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16\\}"

if { ${have_cl_khr_fp64} } {
  gdb_test "whatis d" "type = double"
  gdb_test "p sizeof(d)" " = 8"
  gdb_test "print d" " = 1"
  gdb_test "whatis d2" "type = double2"
  gdb_test "p sizeof(d2)" " = 16"
  gdb_test "print d2" " = \\{1, 2\\}"
  if { ${opencl_version} >= 110 } {
    gdb_test "whatis d3" "type = double3"
    gdb_test "p sizeof(d3)" " = 32"
    gdb_test "print d3" " = \\{1, 2, 3\\}"
  }
  gdb_test "whatis d4" "type = double4"
  gdb_test "p sizeof(d4)" " = 32"
  gdb_test "print d4" " = \\{1, 2, 3, 4\\}"
  gdb_test "whatis d8" "type = double8"
  gdb_test "p sizeof(d8)" " = 64"
  gdb_test "print d8" " = \\{1, 2, 3, 4, 5, 6, 7, 8\\}"
  gdb_test "whatis d16" "type = double16"
  gdb_test "p sizeof(d16)" " = 128"
  gdb_test "print d16" " = \\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16\\}"
}

# Delete the OpenCL program source
remote_file target delete ${clprogram}
